
#ifndef _ka_graphics_bitmap_h
#define _ka_graphics_bitmap_h

#include "ka-system/types.h"
#include "ka-graphics/geom.h"

namespace ka {
    class Color {
    public:
        Color();
        Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha);
        static Color from4f(float red, float green, float blue, float alpha);
        static void to4f(Color c, float f[]);
        inline uint8_t red() const { return _u.channels[0]; }
        inline void red(uint8_t rv) { _u.channels[0] = rv; }
        inline uint8_t green() const { return _u.channels[1]; }
        inline void green(uint8_t gv) { _u.channels[1] = gv; }
        inline uint8_t blue() const { return _u.channels[2]; }
        inline void blue(uint8_t bv) { _u.channels[2] = bv; }
        inline uint8_t alpha() const { return _u.channels[3]; }
        inline void alpha(uint8_t av) { _u.channels[3] = av; }
        inline uint32_t rgba() const { return _u.packed; }
    private:
        union {
            uint32_t packed;
            uint8_t channels[4];
        } _u;
    };
    
    struct ColorChannel {
        enum {
            NONE,
            GRAY,
            RED,
            GREEN,
            BLUE,
            ALPHA,
            PADDING,
        };
        
        uint8_t type;
        uint8_t bitCount;
    };
    

    
    class Bitmap {
    public:
        /**
         * Supported Bitmap formats
         */
        enum Format {
            FORMAT_NONE,
            FORMAT_RGB565,
            FORMAT_RGBA8888,
        };
        
        Bitmap(uint32_t width, uint32_t height, Format format);
        ~Bitmap();
        void set(int32_t x, int32_t y, Color color);
        Color get(int32_t x, int32_t y) const;
        uint32_t width() const;
        uint32_t height() const;
        
        /**
         * Get the number of bytes per line.
         *
         * uint8_t *topRow = bmp->dataPtr() + (bmp->height()-1) * bmp->stride();
         */
        uint32_t stride() const;
        uint8_t *dataPtr();
        const uint8_t *dataPtr() const;
        void getMetrics(struct BitmapMetrics &mout) const;
    private:
        uint8_t *_data;
        Format _format;
        uint32_t _stride;
        uint32_t _width;
        uint32_t _height;
    };
    
    /**
     * Robust information about the bitmap size and format
     */
    struct BitmapMetrics {
        Bitmap::Format format;
        uint32_t width;
        uint32_t height;
        uint16_t bitsPerSample;
        uint16_t channelCount;
        ColorChannel channels[4];
    };
}

#endif